//-----------------------------------------------------------------------
// <copyright file="Contact.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace Microsoft.Live.Messenger
{
    using System;
    using System.ComponentModel;
    using Microsoft.Live.Core;

    /// <summary>
    ///     Represents a single contact. 
    /// </summary>
    /// <remarks>
    ///     The contact object represents a Messenger User that the User converses with. Each contact may have several associated IMAddress objects.
    /// </remarks>
    public sealed class Contact : INotifyPropertyChanged
    {
        private readonly MessengerEntity entity;
        private readonly User user;

        private IMAddressCollection addresses;

        internal Contact(MessengerEntity entity, User user)
        {
            this.entity = entity;
            this.entity.AttachEvent("CurrentAddressChanging", this.OnCurrentAddressChanging);
            this.entity.AttachEvent("PropertyChanged", this.OnPropertyChanged);

            this.user = user;
        }

        internal MessengerEntity Entity
        {
            get { return this.entity; }
        }

        /// <summary>
        ///     Blocks the contact from viewing the User's presence and initiating
        ///     conversations with the User.
        /// </summary>
        public void Block()
        {
            this.entity.Invoke("Block");
        }

        /// <summary>
        ///     Allows the contact to view the User's presence and initiate
        ///     conversations with the User.
        /// </summary>
        public void Allow()
        {
            this.entity.Invoke("Allow");
        }

        /// <summary>
        ///     All of the <see cref="IMAddress"/>es for the contact.
        /// </summary>
        public IMAddressCollection Addresses
        {
            get
            {
                if (this.addresses == null)
                {
                    this.addresses = new IMAddressCollection(this.entity.GetProperty("Addresses"), this.user);
                }
                return this.addresses;
            }
        }

        /// <summary>
        ///     The current <see cref="IMAddress"/> that should be displayed in the UI. This Address is also 
        ///     the address that should be used to start a new conversation after (for example) double clicking 
        ///     the contact in the UI.
        /// </summary>
        public IMAddress CurrentAddress
        {
            get { return this.user.IMAddressFactory.FindOrCreate(this.entity.GetProperty("CurrentAddress")); }
        }

        /// <summary>
        /// Gets the groups that the instant messaging address belongs to.
        /// </summary>
        public Group[] Groups
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        ///     Gets whether the address is allowed to view the User's presence.
        /// </summary>
        public bool IsAllowed
        {
            get { return this.entity.GetProperty<bool>("IsAllowed"); }
        }

        /// <summary>
        ///     Gets whether the address is blocked from viewing the User's presence.
        /// </summary>
        public bool IsBlocked
        {
            get { return this.entity.GetProperty<bool>("IsBlocked"); }
        }

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        /// <summary>
        ///     Raised when the current address of the contact is changed.
        /// </summary>
        /// <remarks>
        ///     This event should only be used if the old value is needed upon change (for example to
        ///     remove event handlers). Consider using the <see cref="PropertyChanged"/> event if the 
        ///     old value is not needed.
        /// </remarks>
        public event AddressChangingEventHandler CurrentAddressChanging;

        private void OnCurrentAddressChanging(object sender, MessengerEventArgs e)
        {
            IMAddress oldAddress = this.user.IMAddressFactory.FindOrCreate(e.Entity.GetProperty("OldAddress"));
            IMAddress newAddress = this.user.IMAddressFactory.FindOrCreate(e.Entity.GetProperty("NewAddress"));

            this.OnCurrentAddressChanging(
                new AddressChangingEventArgs(
                    oldAddress,
                    newAddress));
        }

        /// <summary>
        ///     Raises the <see cref="CurrentAddressChanging"/> event
        /// </summary>
        /// <param name="oldAddress"></param>
        /// <param name="newAddress"></param>
        private void OnCurrentAddressChanging(AddressChangingEventArgs e)
        {
            if (this.CurrentAddressChanging != null)
            {
                this.CurrentAddressChanging(this, e);
            }
        }

        private void OnPropertyChanged(object sender, MessengerEventArgs e)
        {
            this.OnPropertyChanged(
                new PropertyChangedEventArgs(
                    e.Entity.GetProperty<string>("PropertyName")));
        }

        private void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, e);
            }
        }
    }
}